package com.example.networkdemo.network

import android.content.Context
import android.net.ConnectivityManager
import android.net.LinkProperties
import android.net.Network
import android.net.NetworkCapabilities
import android.util.Log

object DoNetworkManager {

    const val STATE_UNKNOWN = 0
    const val STATE_MOBILE = 1
    const val STATE_WIFI = 2

    private val mNetworkListener = mutableListOf<NetworkListener>()

    private var currentConnectState = STATE_UNKNOWN

    @Volatile
    private var isRegistered = false
    private const val TAG = "DoNetworkManager"

    private fun registerDefaultNetworkCallback(context: Context) {
        isRegistered = true
        val cm = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        cm.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
            override fun onAvailable(network: Network) {
                Log.e(TAG, "The default network is now: " + network)
            }

            override fun onLost(network: Network) {
                Log.e(TAG, "The application no longer has a default network. The last default network was " + network)
                handle(null)
            }

            override fun onCapabilitiesChanged(
                network: Network,
                networkCapabilities: NetworkCapabilities
            ) {
                Log.d(TAG, "The default network changed capabilities: " + networkCapabilities)
                handle(networkCapabilities)
            }

            override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) {
                Log.i(TAG, "The default network changed link properties: " + linkProperties)
            }
        })
    }

    @Synchronized
    fun addNetworkListener(context: Context, l: NetworkListener) {
        mNetworkListener.add(l)
        if (!isRegistered) {
            registerDefaultNetworkCallback(context)
        }
        Log.d(TAG, "callback1: $currentConnectState")
        l.onNetChanged(currentConnectState)
    }

    @Synchronized
    fun removeNetworkListener(l: NetworkListener) {
        if (mNetworkListener.contains(l)) {
            mNetworkListener.remove(l)
        }
    }

    @JvmStatic
    @Deprecated("use ")
    fun getNetworkState(context: Context): Int {
        val cm =
            context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val networkInfo = cm.activeNetworkInfo
        if (networkInfo != null && networkInfo.isConnected) {
            when (networkInfo.type) {
                ConnectivityManager.TYPE_WIFI -> {
                    return STATE_WIFI
                }
                ConnectivityManager.TYPE_MOBILE -> {
                    return STATE_MOBILE
                }
            }
        }
        return STATE_UNKNOWN
    }

    private fun getNetworkStateNew(context: Context): Int {
        val cm =
            context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val currentNetwork = cm.activeNetwork
        if (currentNetwork != null) {
            val caps = cm.getNetworkCapabilities(currentNetwork)
//            val linkProperties = cm.getLinkProperties(currentNetwork)
            handle(caps)
        }
        return currentConnectState
    }

    private fun handle(caps: NetworkCapabilities?) {
        if (caps != null) {
            if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
                if (
                    caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
                    caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
                ) {
                    setResult(STATE_WIFI)
                    return
                } else if (
                    caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                    caps.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
                ) {
                    setResult(STATE_MOBILE)
                    return
                }
            }
        }
        setResult(STATE_UNKNOWN)
        return
    }

    @Synchronized
    private fun setResult(newState: Int) {
        // 未知网络
        if (currentConnectState == newState) {
            return
        } else {
            currentConnectState = newState
            mNetworkListener.forEach { it.onNetChanged(newState) }
        }
    }

}